package com.jiangli.service.impl;

import com.alibaba.druid.util.StringUtils;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.jiangli.context.BaseContext;
import com.jiangli.dto.MerchantDTO;
import com.jiangli.dto.MerchantPageQueryDTO;
import com.jiangli.entity.Merchant;
import com.jiangli.exception.BaseException;
import com.jiangli.mapper.DishFlavorMapper;
import com.jiangli.mapper.DishMapper;
import com.jiangli.mapper.MerchantMapper;
import com.jiangli.mapper.UserFavoriteMapper;
import com.jiangli.result.PageResult;
import com.jiangli.service.AdminDishService;
import com.jiangli.service.AdminMerchantService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class AdminMerchantServiceImpl implements AdminMerchantService {


    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private UserFavoriteMapper userFavoriteMapper;
    private static final String MERCHANT_COUNT = "merchant:total:count:";
    private static final String MERCHANT_RECOMMEND = "merchant:recommend:";
    private static final String MERCHANT_DETAIL_PREFIX="merchant:detail:";
    private static final String DISH_DETAIL_PREFIX="dish:detail:";
    // 常量定义
    private static final String MERCHANT_METADATA_KEY = "merchant:metadata:all"; // 存储所有商家信息的缓存键
    private static final String MERCHANT_LOCK_KEY = "merchant:lock:metadata";    // 分布式锁键
    private static final String EMPTY_MARKER = "EMPTY";                          // 空列表标记
    private static final long CACHE_EXPIRE_HOURS = 1;                            // 缓存过期时间（1小时）


    @Autowired
    private DishFlavorMapper dishFlavorMapper;
    @Autowired
    private AdminDishService adminDishService;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private MerchantMapper merchantMapper;

    @Autowired
    private DishMapper dishMapper;
    public PageResult pageQuery(MerchantPageQueryDTO merchantPageQueryDTO) {
        if (merchantPageQueryDTO.getPage()<0){
            merchantPageQueryDTO.setPage(1);
        }
        if (merchantPageQueryDTO.getPageSize()<0||merchantPageQueryDTO.getPageSize()>20){
            merchantPageQueryDTO.setPageSize(10);
        }
        PageHelper.startPage(merchantPageQueryDTO.getPage(),merchantPageQueryDTO.getPageSize());
        Page<Merchant> page=merchantMapper.pageQuery(merchantPageQueryDTO);
        int count=(int) page.getTotal();
        return new PageResult(count, page );
    }

    @Override
    @Transactional
    public void addMerchant(MerchantDTO merchantDTO) {
        if (merchantDTO == null) {
            throw new BaseException("传入商家信息为null");
        }
        Merchant merchant = new Merchant();
        BeanUtils.copyProperties(merchantDTO, merchant);
        if (BaseContext.getCurrentId() != null) {
            merchant.setCreateUser(BaseContext.getCurrentId());
        } else {
            merchant.setCreateUser(1L);
        }
        merchant.setStatus(0);
        merchant.setMerchantRating(0);
        merchant.setRatingCount(0L);

        // 1) 插入数据库
        merchantMapper.add(merchant);

        // 2) 清理影响范围较大的缓存（先删总量/元数据/推荐...）
        //    采用双删思路：删除一次 -> 写缓存 -> 再异步或再次删除（如果需要）
        deleteCache();

        // 3) 主动写入该商家详情缓存，确保立即可读（防止其他请求读到 EMPTY）
        String detailKey = MERCHANT_DETAIL_PREFIX + merchant.getId();
        try {
            String json = objectMapper.writeValueAsString(merchant);
            // 选择中等 TTL，单位分钟（若你希望用小时可调整）
            redisTemplate.opsForValue().set(detailKey, json, CACHE_EXPIRE_HOURS, TimeUnit.HOURS);
        } catch (JsonProcessingException e) {
            log.error("序列化商家对象失败，跳过写入缓存", e);
        }

        // 4) （可选）再次删除缓存（双删）：为了防止并发读写，推荐在异步线程/消息中再删除一次。
        //    注意：不要在事务里 Thread.sleep()。若需要双删，可通过异步任务或 MQ 实现。
    }


    @Transactional
    public void delete(Long merchantId) {
        if(merchantId==null){
            throw new BaseException("id为null");
        }
        List<Long> dishIds = dishMapper.selectDishIdsByMerchantId(merchantId);
      for (
            Long dishId : dishIds
       ){
          dishFlavorMapper.deletByDishId(dishId);
          userFavoriteMapper.deleteByDishId(dishId);
            adminDishService.deleteDish(dishId);
        }
        merchantMapper.delete(merchantId);
      deleteCache();
    }

    @Transactional
    public void update(MerchantDTO merchantDTO) {
        if(merchantDTO.getId()==null){
            throw new BaseException("商家id为null");
        }
        Merchant merchant=new Merchant();
        BeanUtils.copyProperties(merchantDTO,merchant);
        if(merchantDTO.getMerchantName()==null||merchantDTO.getMerchantName().trim().equals("")){
            merchant.setMerchantName(null);
        }

        merchantMapper.update(merchant);
        log.warn("更新商家：{}",merchant);
        deleteCache();
    }

    @Override
    public PageResult query(MerchantDTO merchantDTO) {
        MerchantPageQueryDTO merchantPageQueryDTO=new MerchantPageQueryDTO();
        BeanUtils.copyProperties(merchantDTO,merchantPageQueryDTO);
        Page<Merchant> page=merchantMapper.pageQuery(merchantPageQueryDTO);

        List<Merchant> result = page.getResult();
        int count=result.size();

        return new PageResult(count,page);
    }

    public void deleteCache(){
        // 删除总数缓存
        redisTemplate.delete(MERCHANT_COUNT);
        // 删除全量商家元数据
        redisTemplate.delete(MERCHANT_METADATA_KEY);
        // 删除所有商家详情缓存
        Set<String> detailKeys = redisTemplate.keys(MERCHANT_DETAIL_PREFIX + "*");
        if (detailKeys != null && !detailKeys.isEmpty()) {
            redisTemplate.delete(detailKeys);
        }
        // 删除推荐商家缓存
        Set<String> recommendKeys = redisTemplate.keys(MERCHANT_RECOMMEND + "*");
        if (recommendKeys != null && !recommendKeys.isEmpty()) {
            redisTemplate.delete(recommendKeys);
        }
    }


}
